﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using nelech.Models.DBModel;
using System.Drawing.Imaging;
using System.Drawing;

namespace nelech.Controllers.Utils
{
    public static class SharedUtils
    {
        public static string SaveImage(Stream stream, string virtualFolder, string fileName, string extension, HttpServerUtilityBase server, long quality)
        {
            return SaveImage(stream, virtualFolder, fileName, extension, server, quality, true);
        }

        public static string SaveImage(Stream stream, string virtualFolder, string fileName, string extension, HttpServerUtilityBase server, long quality, bool watermark)
        {
            var path = server.MapPath(virtualFolder);
            var filePath = Path.Combine(path, fileName + extension);

            using (var bitmap = new System.Drawing.Bitmap(stream))
            {
                if(watermark) AddWatermark(server, bitmap);

                var codecInfo = GetEncoderInfo(GetMimetypeFromExtension(extension));
                var ps = new EncoderParameters(1);
                ps.Param[0] = new EncoderParameter(Encoder.Quality, quality);
                bitmap.Save(filePath, codecInfo, ps);
            }

            if (!virtualFolder.EndsWith("/"))
                virtualFolder += '/';
            var virtualFilePath = virtualFolder + fileName + extension;
            return virtualFilePath;
        }

        private static void AddWatermark(HttpServerUtilityBase server, Bitmap bitmap)
        {
            using (var newGraphics = Graphics.FromImage(bitmap))
            {
                var x = (int)(bitmap.Width * 0.35);
                var y = (int)(bitmap.Height * 0.35);
                var width = (int)(bitmap.Width * 0.3);
                var height = width;

                var signPath = server.MapPath("/Upload/Sign/sign.png");
                using (var watermark = System.Drawing.Image.FromFile(signPath))
                {
                    newGraphics.DrawImage(watermark, new Rectangle(x, y, width, height),
                        0, 0, watermark.Width, watermark.Height, GraphicsUnit.Pixel);
                    newGraphics.Save();
                }
            }
        }

        public static string SaveImage(Stream stream, string virtualFolder, string fileName, string extension, HttpServerUtilityBase server)
        {
            var path = server.MapPath(virtualFolder);
            var filePath = Path.Combine(path, fileName + extension);
            if (!virtualFolder.EndsWith("/"))
                virtualFolder += '/';
            var virtualFilePath = virtualFolder + fileName + extension;
            return virtualFilePath;
        }

        private static string GetMimetypeFromExtension(string extension)
        {
            extension = extension.Substring(1);
            switch (extension.ToLower())
            {
                case "jpg":
                    return "image/jpeg";
                default:
                    return string.Format("image/{0}", extension);
            }
        }

        internal static string SaveDoc(string text, string virtualFolder, HttpServerUtilityBase server)
        {
            var path = server.MapPath(virtualFolder);
            var fileName = "Event";
            var extension = ".html";
            var newFileName = string.Format("{0}_{1}{2}", fileName, Guid.NewGuid(), extension);
            var filePath = Path.Combine(path, newFileName);
            System.IO.File.WriteAllText(filePath, text, System.Text.Encoding.UTF8);
            if (!virtualFolder.EndsWith("/"))
                virtualFolder += '/';
            var virtualFilePath = virtualFolder + newFileName;
            return virtualFilePath;
        }

        internal static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            ImageCodecInfo[] encoders;
            encoders = ImageCodecInfo.GetImageEncoders();
            for (int j = 0; j < encoders.Length; ++j)
            {
                if (encoders[j].MimeType.Equals(mimeType, StringComparison.OrdinalIgnoreCase))
                    return encoders[j];
            }
            return null;
        }

        internal static string GetUniqueFileName(string fullFileName)
        {
            var fileName = Path.GetFileNameWithoutExtension(fullFileName);
            var extension = Path.GetExtension(fileName);
            var newFileName = string.Format("{0}_{1}{2}", fileName, Guid.NewGuid(), extension);
            return newFileName;
        }

        public static AdvertsPlaces AdvertPac(List<Advert> advertsTop, List<Advert> advertsRight, List<Advert> advertsLeft, List<Advert> advertsButtom)
        {
            Random random = new Random();
            Advert advertButtom = null;
            Advert advertTop = null;
            Advert advertRight = null;
            Advert advertLeft = null;
            if (advertsTop.Count() > 0)
            {
                int num = random.Next(0, advertsTop.Count());
                advertTop = advertsTop[num];
            }
            if (advertsRight.Count() > 0)
            {
                int num = random.Next(0, advertsRight.Count());
                advertRight = advertsRight[num];
            }
            if (advertsLeft.Count() > 0)
            {
                int num = random.Next(0, advertsLeft.Count());
                advertLeft = advertsLeft[num];
            }
            if (advertsButtom.Count() > 0)
            {
                int num = random.Next(0, advertsButtom.Count());
                advertButtom = advertsButtom[num];
            }
            var advertsPlaces = new AdvertsPlaces() { advertLeft = advertLeft, advertButtom = advertButtom, advertRight = advertRight, advertTop = advertTop };
            return advertsPlaces;
        }

        public static double Distance(float? srcLon, float? srcLat, float? dstLon, float? dstLat)
        {
            return Math.Sqrt(Math.Pow(dstLon.Value - srcLon.Value, 2.0) + Math.Pow(dstLat.Value - srcLat.Value, 2.0));
        }

      

        internal static List<Track> FreeSearchTrack(List<Track> tracks, string searchString)
        {
            if (string.IsNullOrEmpty(searchString))
                return tracks;
          //  var tokens = searchString.Split(' ');
            var dictionary = new Dictionary<int, Pair<Track, int>>();
            var matchesPhressInTittle = tracks.Where(p => p.title.ContainsWholeWorld(searchString));
            foreach (var match1 in matchesPhressInTittle)
            {
                if (!dictionary.ContainsKey(match1.number))
                    dictionary[match1.number] = new Pair<Track, int>(match1, 100);
                dictionary[match1.number].Second++;
            }
            var matchesPhressInSummery = tracks.Where(p => p.summary.ContainsWholeWorld(searchString));
            foreach (var match1 in matchesPhressInSummery)
            {
                if (!dictionary.ContainsKey(match1.number))
                    dictionary[match1.number] = new Pair<Track, int>(match1, 10);
                dictionary[match1.number].Second++;
            }
            var matchesPhress = tracks.Where(p => SearchTokenInTrack(searchString, p));
            foreach (var match1 in matchesPhress)
            {
                if (!dictionary.ContainsKey(match1.number))
                    dictionary[match1.number] = new Pair<Track, int>(match1, 1);
                dictionary[match1.number].Second++;
            }
           

            return dictionary.Values.OrderByDescending(p => p.Second, new IntComparer()).Select(p => p.First).ToList();
        }

        private static bool SearchTokenInTrack(string token, Track track)
        {
            return (track.details != null && track.details.ContainsWholeWorld(token)) || (track.summary != null && track.summary.ContainsWholeWorld(token))
                 || (track.coming != null && track.coming.ContainsWholeWorld(token)) || (track.title != null && track.title.ContainsWholeWorld(token));
        }

        internal static List<Munach> FreeSearchMunach(List<Munach> munachs, string searchString)
        {
            if (string.IsNullOrEmpty(searchString))
                return munachs;
           // var tokens = searchString.Split(' ');
            var dictionary = new Dictionary<int, Pair<Munach, int>>();
            var matchesPhress = munachs.Where(p => SearchTokenInMunach(searchString, p));
            foreach (var match1 in matchesPhress)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Munach, int>(match1, 1);
                dictionary[match1.id].Second++;
            }
            //foreach (var token in tokens)
            //{
            //    var matches = munachs.Where(p => SearchTokenInMunach(token, p));
            //    foreach (var match in matches)
            //    {
            //        if (!dictionary.ContainsKey(match.id))
            //            dictionary[match.id] = new Pair<Munach, int>(match, 0);
            //        dictionary[match.id].Second++;
            //    }
            //}

            return dictionary.Values.OrderByDescending(p => p.Second, new IntComparer()).Select(p => p.First).ToList();
        }

        private static bool SearchTokenInMunach(string token, Munach munach)
        {
            return (munach.name != null && munach.name.ContainsWholeWorld(token)) || (munach.description != null && munach.description.ContainsWholeWorld(token))
                 || (munach.nearby != null && munach.nearby.ContainsWholeWorld(token));
        }


        public static bool ContainsWholeWorld(this string str, string world)
        {
            return str.Contains(' ' + world + ' ') || str.Contains(' ' + world) || str.Contains(world + ' ') || str.Contains(world + '.') || str.Contains(world + ',')
                 || str.Contains(' ' + world + "ים") || str.Contains(" ב" + world + "ים") || str.Contains(" כ" + world + "ים") || str.Contains(" ל" + world + "ים") || str.Contains(" ה" + world + "ים") || str.Contains(" ש" + world + "ים") || str.Contains(" מ" + world + "ים") || str.Contains(world + "ות") || str.Contains(world + "ה") || str.Contains(world + ':') || str.Contains(world + '"') || str.Contains('ב' + world)
                  || str.Contains('ל' + world) || str.Contains('כ' + world) || str.Contains('מ' + world) || str.Contains('ש' + world) || str.Contains('ה' + world)
                  || str.Equals(world);
        }

        internal static List<Place> FreeSearchPlace(List<Place> places, string searchString)
        {
            if (string.IsNullOrEmpty(searchString))
                return places;
            //var tokens = searchString.Split(' ');
            var dictionary = new Dictionary<int, Pair<Place, int>>();
            var matchesPhressInTittle = places.Where(p => p.name.ContainsWholeWorld(searchString));
            foreach (var match1 in matchesPhressInTittle)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Place, int>(match1, 100);
                dictionary[match1.id].Second++;
            }
            var matchesPhressInSummery = places.Where(p => p.summary.ContainsWholeWorld(searchString));
            foreach (var match1 in matchesPhressInSummery)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Place, int>(match1, 10);
                dictionary[match1.id].Second++;
            }
            var matchesPhress = places.Where(p => SearchTokenInPlace(searchString, p));
            foreach (var match1 in matchesPhress)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Place, int>(match1, 1);
                dictionary[match1.id].Second++;
            }
            //foreach (var token in tokens)
            //{
            //    var matches = places.Where(p => SearchTokenInPlace(token, p));
            //    foreach (var match in matches)
            //    {
            //        if (!dictionary.ContainsKey(match.id))
            //            dictionary[match.id] = new Pair<Place, int>(match, 0);
            //        dictionary[match.id].Second++;
            //    }
            //}

            return dictionary.Values.OrderByDescending(p => p.Second, new IntComparer()).Select(p => p.First).ToList();
        }

        private static bool SearchTokenInPlace(string token, Place place)
        {
            return (place.name != null && place.name.ContainsWholeWorld(token)) || (place.coming != null && place.coming.ContainsWholeWorld(token))
                 || (place.description != null && place.description.ContainsWholeWorld(token)) || (place.history != null && place.history.ContainsWholeWorld(token));
                 

        }

      

        internal static List<Maayan> FreeSearchSpring(List<Maayan> springs, string searchString)
        {
            if (string.IsNullOrEmpty(searchString))
                return springs;
           // var tokens = searchString.Split(' ');
            var dictionary = new Dictionary<int, Pair<Maayan, int>>();
            var matchesPhressInTittle = springs.Where(p => p.name.ContainsWholeWorld(searchString));
            foreach (var match1 in matchesPhressInTittle)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Maayan, int>(match1, 100);
                dictionary[match1.id].Second++;
            }
            var matchesPhressInSummery = springs.Where(p => p.summary.ContainsWholeWorld(searchString));
            foreach (var match1 in matchesPhressInSummery)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Maayan, int>(match1, 10);
                dictionary[match1.id].Second++;
            }
            var matchesPhress = springs.Where(p => SearchTokenInSpring(searchString, p));
            foreach (var match1 in matchesPhress)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Maayan, int>(match1, 1);
                dictionary[match1.id].Second++;
            }
            //foreach (var token in tokens)
            //{
            //    var matches = springs.Where(p => SearchTokenInSpring(token, p));
            //    foreach (var match in matches)
            //    {
            //        if (!dictionary.ContainsKey(match.id))
            //            dictionary[match.id] = new Pair<Maayan, int>(match, 0);
            //        dictionary[match.id].Second++;
            //    }
            //}

            return dictionary.Values.OrderByDescending(p => p.Second, new IntComparer()).Select(p => p.First).ToList();
        }

        private static bool SearchTokenInSpring(string token, Maayan spring)
        {
            return
                (spring.description != null && spring.description.ContainsWholeWorld(token)) ||
                (spring.name != null && spring.name.ContainsWholeWorld(token)) ||
                (spring.summary != null && spring.summary.ContainsWholeWorld(token)) ||
                (spring.coming != null && spring.coming.ContainsWholeWorld(token)) ||
                (spring.history != null && spring.history.ContainsWholeWorld(token));
        }

        internal static List<Text> FreeSearchText(List<Text> texts, string searchString)
        {
            if (string.IsNullOrEmpty(searchString))
                return texts;
           // var tokens = searchString.Split(' ');
            var dictionary = new Dictionary<int, Pair<Text, int>>();
            var matchesPhress = texts.Where(p => SearchTokenInText(searchString, p));
            foreach (var match1 in matchesPhress)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Text, int>(match1, 1000);
                dictionary[match1.id].Second++;
            }
            //foreach (var token in tokens)
            //{
            //    var matches = texts.Where(p => SearchTokenInText(token, p));
            //    foreach (var match in matches)
            //    {
            //        if (!dictionary.ContainsKey(match.id))
            //            dictionary[match.id] = new Pair<Text, int>(match, 0);
            //        dictionary[match.id].Second++;
            //    }
            //}

            return dictionary.Values.OrderByDescending(p => p.Second, new IntComparer()).Select(p => p.First).ToList();
        }

        private static bool SearchTokenInText(string token, Text text)
        {
            return
                (text.text1 != null && text.text1.ContainsWholeWorld(token)) ||
                (text.title != null && text.title.ContainsWholeWorld(token));
        }


        internal static List<Zimer> FreeSearchZimer(List<Zimer> zimers, string searchString)
        {
            if (string.IsNullOrEmpty(searchString))
                return zimers;
            //var tokens = searchString.Split(' ');
            var dictionary = new Dictionary<int, Pair<Zimer, int>>();
            var matchesPhress = zimers.Where(p => SearchTokenInZimer(searchString, p));
            foreach (var match1 in matchesPhress)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Zimer, int>(match1, 1000);
                dictionary[match1.id].Second++;
            }
            //foreach (var token in tokens)
            //{
            //    var matches = zimers.Where(p => SearchTokenInZimer(token, p));
            //    foreach (var match in matches)
            //    {
            //        if (!dictionary.ContainsKey(match.id))
            //            dictionary[match.id] = new Pair<Zimer, int>(match, 0);
            //        dictionary[match.id].Second++;
            //    }
            //}

            return dictionary.Values.OrderByDescending(p => p.Second, new IntComparer()).Select(p => p.First).ToList();
        }

        private static bool SearchTokenInZimer(string token, Zimer zimer)
        {
            return (zimer.description != null && zimer.description.ContainsWholeWorld(token)) ||
                (zimer.name != null && zimer.name.ContainsWholeWorld(token));
        }

        internal static List<Forum> FreeSearchForum(List<Forum> forums, string searchString)
        {
            if (string.IsNullOrEmpty(searchString))
                return null;
           // var tokens = searchString.Split(' ');
            var dictionary = new Dictionary<int, Pair<Forum, int>>();
            var matchesPhress = forums.Where(p => SearchTokenInForum(searchString, p));
            foreach (var match1 in matchesPhress)
            {
                if (!dictionary.ContainsKey(match1.id))
                    dictionary[match1.id] = new Pair<Forum, int>(match1, 1000);
                dictionary[match1.id].Second++;
            }
            //foreach (var token in tokens)
            //{
            //    var matches = forums.Where(p => SearchTokenInForum(token, p));
            //    foreach (var match in matches)
            //    {
            //        if (!dictionary.ContainsKey(match.id))
            //            dictionary[match.id] = new Pair<Forum, int>(match, 0);
            //        dictionary[match.id].Second++;
            //    }
            //}

            return dictionary.Values.OrderByDescending(p => p.Second, new IntComparer()).Select(p => p.First).ToList();
        }

        private static bool SearchTokenInForum(string token, Forum forum)
        {
            return (forum.name != null && forum.name.ContainsWholeWorld(token)) || (forum.text != null && forum.text.ContainsWholeWorld(token)) || (forum.title != null && forum.title.ContainsWholeWorld(token));
        }


        internal static IQueryable<Track> FreeSearchTrack(IQueryable<Track> tracks, string searchString)
        {
            throw new NotImplementedException();
        }
    }

    internal class Pair<TFirst, TSecond>
    {
        public TFirst First { get; set; }
        public TSecond Second { get; set; }
        public Pair(TFirst first, TSecond second)
        {
            First = first;
            Second = second;
        }
    }
}
